/**
 * Copyright (c) 2010 BullionXpress.com,
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

package com.bullionxpress.server.impl;

import com.bullionxpress.server.application.ServerGlobals;
import java.rmi.RemoteException;
import com.bullionxpress.shared.model.User;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import com.bullionxpress.shared.model.Account;
import com.bullionxpress.shared.service.AccountDatabase;
import com.bullionxpress.shared.service.DuplicateUserIDException;
import com.bullionxpress.shared.service.InvalidUserIDFormatException;
import com.bullionxpress.shared.service.MissingInformationException;
import com.bullionxpress.shared.service.UserDatabase;
import com.bullionxpress.shared.service.UserNotFoundException;
import com.bullionxpress.shared.util.Log;
import com.bullionxpress.shared.util.Utility;

/*
 * 
 */
public class UserRegistrar extends java.rmi.server.UnicastRemoteObject implements UserDatabase {
    Connection conn = null;
    Statement statement = null;
    public UserRegistrar() throws RemoteException {
        //What should go in the constructor?
        connect();
    }
    public void connect() {
        try {
            conn = DatabaseManager.getConnection();

            try {
                statement = conn.createStatement();
                statement.executeUpdate("CREATE TABLE IF NOT EXISTS users (userid varchar(16), password varchar(16), email varchar(64), phone varchar(32), address varchar(256), createDate long, country varchar(32), city varchar(32), postalcode varchar(16), firstname varchar(16), lastname varchar(32), province varchar(32), admin boolean) ");
            } catch (Exception ex) {
                System.out.println(ex);
                ex.printStackTrace();
            }
        } catch (Exception ex) {
            System.out.println(ex);
            ex.printStackTrace();
        }
    }

    public User[] getAll() {
        try {
            String query = "SELECT * FROM users";
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            ResultSet result = statement.executeQuery(query);
            Vector v = new Vector();
            while (result.next()) {
                User acct = get(result.getString("userid"));
                v.addElement(acct);
            }
            User[] UserList = new User[v.size()];
            for (int i = 0; i < v.size(); i++) {
                UserList[i] = (User) v.get(i);
            }
            return UserList;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public User get(String userid) throws UserNotFoundException {

        if (userid == null) {
            throw new IllegalArgumentException();
        }

        String query = "SELECT * FROM users WHERE userid = '" + userid + "'";
        ResultSet result = null;
        boolean r = false;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            result = statement.executeQuery(query);
            r = result.next();
        } catch (Exception ex) {
        }

        if (r) {
            User u = new User();
            try {
                String email = result.getString("email");
                u.setUserID(result.getString("userid"));
                u.setPassword(result.getString("password"));
                u.setAddress(result.getString("address"));
                u.setEmail(email);
                u.setTelephone(result.getString("phone"));
                u.setCreateDate(result.getLong("createDate"));
                u.setCountry(result.getString("country"));
                u.setPostalCode(result.getString("postalcode"));
                u.setCity(result.getString("city"));
                u.setFirstName(result.getString("firstname"));
                u.setLastName(result.getString("lastname"));
                u.setProvince(result.getString("province"));
                u.setAdmin(result.getBoolean("admin"));

            } catch(Exception ex){
                ex.printStackTrace();
                throw new UserNotFoundException();
            }
            return u;
        } else {
            throw new UserNotFoundException("Username: " + userid + " is not found");
        }
    }

    public boolean isValid(User u) 
    {
        if( ServerGlobals.testing){
            return true;
        }
        if( u.getAddress() == null ){
            System.out.println("Bad address");
            return false;
        }
        else if(u.getTelephone() == null)
        {
            System.out.println("Bad Telephone");
            return false;
        }
        else if( u.getUserID() == null ){
            System.out.println("Bad User ID");
            return false;
        }
        else if( u.getPassword() == null ){
            System.out.println("Bad Password");
            return false;
        }
        else if( u.getEmail() == null ){
            System.out.println("Bad Email");
            return false;
        }
        // specific checks.
        else if(!Utility.isValidEmail(u.getEmail()))
        {
            return false;
        }
        else if(!Utility.isValidPassword(u.getPassword()))
        {
            return false;
        }
        else if(!Utility.isValidUserID(u.getUserID()))
        {
            return false;
        }
        return true;
    }

    public void register(User b) throws DuplicateUserIDException, InvalidUserIDFormatException, MissingInformationException {

        if (b == null) {
            throw new IllegalArgumentException();
        } else if (b.getUserID() == null) {
            throw new InvalidUserIDFormatException();
        } 

        try {
            User a = get(b.getUserID());
            throw new DuplicateUserIDException();
        } catch(UserNotFoundException ex){
            
        }

        if( !isValid(b)){
            throw new MissingInformationException();
        }

        String query = "INSERT INTO users (userid, password, phone, address, email, createDate, country, city, postalcode, firstname, lastname, admin) VALUES ('" + b.getUserID() + "', '" + b.getPassword() + "', '" + b.getTelephone() + "','" + b.getAddress() + "', '" + b.getEmail() + "', " + b.getCreateDate() + ", '" + b.getCountry() + "', '" + b.getCity() + "', '" + b.getPostalCode() + "', '" + b.getFirstName() + "', '" + b.getLastName() + "', false)";
        int n = 0;
        try {
            Log.info(query);
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            n = statement.executeUpdate(query);
        } catch (SQLException ex) {
            ex.printStackTrace();
            Log.info(ex);
        }
        if (n != 1) {
            Log.info("" + n);
            throw new DuplicateUserIDException();
        }
    }

    public void delete(String id) throws UserNotFoundException, InvalidUserIDFormatException {

        if (id == null) {
            throw new IllegalArgumentException();
        } 

        String sql = "DELETE FROM users WHERE userid = '" + id + "'";

        int n = 0;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            n = statement.executeUpdate(sql);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }

        if (n < 1) {
            throw new UserNotFoundException();
        }

    }

    public int count() {
        int r = 0;
        User[] b = getAll();
        return b.length;
    }

    public void save(User u) throws UserNotFoundException, InvalidUserIDFormatException, MissingInformationException {
        if( u == null ){
            throw new IllegalArgumentException("User cannot be null");
        }
        if( u.getUserID() == null ){
            throw new InvalidUserIDFormatException();
        }
        if( !isValid( u )){
            throw new MissingInformationException();
        }
        if( get(u.getUserID()) == null ){
            throw new UserNotFoundException("user is not found");
        }

        String query = "UPDATE users SET password = '" + u.getPassword() + 
                       "', phone = '" + u.getTelephone() +
                       "', address = '" + u.getAddress() +
                       "', email =  '" + u.getEmail() +
                       "', createDate = " + u.getCreateDate() +
                       ", country = '" + u.getCountry() +
                       "', city = '" + u.getCity() +
                       "', postalcode = '" + u.getPostalCode() +
                       "', firstname = '" + u.getFirstName() +
                       "', lastname = '" + u.getLastName() +
                       "', province = '" + u.getProvince() +
                       "' WHERE userid = '" + u.getUserID() + "'";
        int n = 0;
        try {
            conn = DatabaseManager.getConnection();
            statement = conn.createStatement();
            n = statement.executeUpdate(query);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
        if( n != 1 ){
            throw new IllegalStateException("Not supposed to happen");
        }
    }
}
